sha512.js ➔ sha512   A
last analyzed

Complexity

Conditions 4

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 23
dl 0
loc 28
ccs 20
cts 20
cp 1
crap 4
rs 9.328
c 0
b 0
f 0
1
/**
2
 * @license
3
 * Copyright (c) 2020 UMI
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in all
13
 * copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
 * SOFTWARE.
22
 */
23
24
'use strict'
25
26 1
const sha512K = [
27
  [0x428a2f98, 0xd728ae22], [0x71374491, 0x23ef65cd], [0xb5c0fbcf, 0xec4d3b2f], [0xe9b5dba5, 0x8189dbbc], [0x3956c25b, 0xf348b538],
28
  [0x59f111f1, 0xb605d019], [0x923f82a4, 0xaf194f9b], [0xab1c5ed5, 0xda6d8118], [0xd807aa98, 0xa3030242], [0x12835b01, 0x45706fbe],
29
  [0x243185be, 0x4ee4b28c], [0x550c7dc3, 0xd5ffb4e2], [0x72be5d74, 0xf27b896f], [0x80deb1fe, 0x3b1696b1], [0x9bdc06a7, 0x25c71235],
30
  [0xc19bf174, 0xcf692694], [0xe49b69c1, 0x9ef14ad2], [0xefbe4786, 0x384f25e3], [0x0fc19dc6, 0x8b8cd5b5], [0x240ca1cc, 0x77ac9c65],
31
  [0x2de92c6f, 0x592b0275], [0x4a7484aa, 0x6ea6e483], [0x5cb0a9dc, 0xbd41fbd4], [0x76f988da, 0x831153b5], [0x983e5152, 0xee66dfab],
32
  [0xa831c66d, 0x2db43210], [0xb00327c8, 0x98fb213f], [0xbf597fc7, 0xbeef0ee4], [0xc6e00bf3, 0x3da88fc2], [0xd5a79147, 0x930aa725],
33
  [0x06ca6351, 0xe003826f], [0x14292967, 0x0a0e6e70], [0x27b70a85, 0x46d22ffc], [0x2e1b2138, 0x5c26c926], [0x4d2c6dfc, 0x5ac42aed],
34
  [0x53380d13, 0x9d95b3df], [0x650a7354, 0x8baf63de], [0x766a0abb, 0x3c77b2a8], [0x81c2c92e, 0x47edaee6], [0x92722c85, 0x1482353b],
35
  [0xa2bfe8a1, 0x4cf10364], [0xa81a664b, 0xbc423001], [0xc24b8b70, 0xd0f89791], [0xc76c51a3, 0x0654be30], [0xd192e819, 0xd6ef5218],
36
  [0xd6990624, 0x5565a910], [0xf40e3585, 0x5771202a], [0x106aa070, 0x32bbd1b8], [0x19a4c116, 0xb8d2d0c8], [0x1e376c08, 0x5141ab53],
37
  [0x2748774c, 0xdf8eeb99], [0x34b0bcb5, 0xe19b48a8], [0x391c0cb3, 0xc5c95a63], [0x4ed8aa4a, 0xe3418acb], [0x5b9cca4f, 0x7763e373],
38
  [0x682e6ff3, 0xd6b2b8a3], [0x748f82ee, 0x5defb2fc], [0x78a5636f, 0x43172f60], [0x84c87814, 0xa1f0ab72], [0x8cc70208, 0x1a6439ec],
39
  [0x90befffa, 0x23631e28], [0xa4506ceb, 0xde82bde9], [0xbef9a3f7, 0xb2c67915], [0xc67178f2, 0xe372532b], [0xca273ece, 0xea26619c],
40
  [0xd186b8c7, 0x21c0c207], [0xeada7dd6, 0xcde0eb1e], [0xf57d4f7f, 0xee6ed178], [0x06f067aa, 0x72176fba], [0x0a637dc5, 0xa2c898a6],
41
  [0x113f9804, 0xbef90dae], [0x1b710b35, 0x131c471b], [0x28db77f5, 0x23047d84], [0x32caab7b, 0x40c72493], [0x3c9ebe0a, 0x15c9bebc],
42
  [0x431d67c4, 0x9c100d4c], [0x4cc5d4be, 0xcb3e42b6], [0x597f299c, 0xfc657e2a], [0x5fcb6fab, 0x3ad6faec], [0x6c44198c, 0x4a475817]
43
]
44
/**
45
 * Безопасный алгоритм хеширования, SHA2-512.
46
 * @see https://en.wikipedia.org/wiki/SHA-2
47
 * @param {ArrayLike<number>} message message
48
 * @returns {number[]}
49
 * @private
50
 */
51
function sha512 (message) {
52 14
  const h = [
53
    [0x6a09e667, 0xf3bcc908], [0xbb67ae85, 0x84caa73b], [0x3c6ef372, 0xfe94f82b], [0xa54ff53a, 0x5f1d36f1],
54
    [0x510e527f, 0xade682d1], [0x9b05688c, 0x2b3e6c1f], [0x1f83d9ab, 0xfb41bd6b], [0x5be0cd19, 0x137e2179]
55
  ]
56 14
  const chunks = sha512PreProcess(message)
57 14
  for (let j = 0, l = chunks.length; j < l; j++) {
58 17
    const w = chunks[j]
59 17
    for (let i = 16; i < 80; i++) {
60 1088
      const s0 = xor64(xor64(rotr64(w[i - 15], 1), rotr64(w[i - 15], 8)), shft64(w[i - 15], 7))
61 1088
      const s1 = xor64(xor64(rotr64(w[i - 2], 19), rotr64(w[i - 2], 61)), shft64(w[i - 2], 6))
62 1088
      w[i] = sum64(sum64(w[i - 16], s0), sum64(w[i - 7], s1))
63
    }
64 17
    sha512Block(h, w)
65
  }
66 14
  const digest = []
67 14
  for (let i = 0; i < 8; i++) {
68 112
    digest[digest.length] = h[i][0] >>> 24 & 0xff
69 112
    digest[digest.length] = h[i][0] >>> 16 & 0xff
70 112
    digest[digest.length] = h[i][0] >>> 8 & 0xff
71 112
    digest[digest.length] = h[i][0] & 0xff
72 112
    digest[digest.length] = h[i][1] >>> 24 & 0xff
73 112
    digest[digest.length] = h[i][1] >>> 16 & 0xff
74 112
    digest[digest.length] = h[i][1] >>> 8 & 0xff
75 112
    digest[digest.length] = h[i][1] & 0xff
76
  }
77 14
  return digest
78
}
79
/**
80
 * @param {ArrayLike<number>} message
81
 * @returns {number[][][]}
82
 * @private
83
 */
84
function sha512PreProcess (message) {
85 14
  const bytes = []
86
  let i
87
  let l
88 14
  for (i = 0, l = message.length + 16 + (128 - ((message.length + 16) % 128)); i < l; i++) {
89 2176
    bytes[i] = message[i] || 0
90
  }
91 14
  bytes[message.length] = 0x80
92 14
  bytes[bytes.length - 2] = ((message.length * 8) >>> 8) & 0xff
93 14
  bytes[bytes.length - 1] = (message.length * 8) & 0xff
94 14
  const chunks = []
95 14
  for (i = 0, l = bytes.length; i < l; i += 128) {
96 17
    const chunk = []
97 17
    for (let j = 0; j < 128; j += 8) {
98 272
      let n = i + j
99 272
      chunk[chunk.length] = [
100
        (bytes[n] << 24) + (bytes[++n] << 16) + (bytes[++n] << 8) + bytes[++n],
101
        (bytes[++n] << 24) + (bytes[++n] << 16) + (bytes[++n] << 8) + bytes[++n]
102
      ]
103
    }
104 17
    chunks[chunks.length] = chunk
105
  }
106 14
  return chunks
107
}
108
/**
109
 * @param {number[][]} h
110
 * @param {number[][]} w
111
 * @returns {number[][]}
112
 * @private
113
 */
114
function sha512Block (h, w) {
115 17
  const a = []
116
  let i
117 17
  for (i = 0; i < 8; i++) {
118 136
    a[i] = [h[i][0], h[i][1]]
119
  }
120 17
  for (i = 0; i < 80; i++) {
121 1360
    const S1 = xor64(xor64(rotr64(a[4], 14), rotr64(a[4], 18)), rotr64(a[4], 41))
122 1360
    const ch = xor64(and64(a[4], a[5]), and64(not64(a[4]), a[6]))
123 1360
    const t1 = sum64(sum64(sum64(a[7], S1), sum64(ch, sha512K[i])), w[i])
124 1360
    const S0 = xor64(xor64(rotr64(a[0], 28), rotr64(a[0], 34)), rotr64(a[0], 39))
125 1360
    const ma = xor64(xor64(and64(a[0], a[1]), and64(a[0], a[2])), and64(a[1], a[2]))
126 1360
    const t2 = sum64(S0, ma)
127 1360
    a[7] = a[6]
128 1360
    a[6] = a[5]
129 1360
    a[5] = a[4]
130 1360
    a[4] = sum64(a[3], t1)
131 1360
    a[3] = a[2]
132 1360
    a[2] = a[1]
133 1360
    a[1] = a[0]
134 1360
    a[0] = sum64(t1, t2)
135
  }
136 17
  for (i = 0; i < 8; i++) {
137 136
    h[i] = sum64(h[i], a[i])
138
  }
139
}
140
/**
141
 * @param {number[]} n
142
 * @param {number} i
143
 * @returns {number[]}
144
 * @private
145
 */
146
function shft64 (n, i) {
147 2176
  return [(n[0] >>> i), (n[1] >>> i) | (n[0] << (32 - i))]
148
}
149
/**
150
 * @param {number[]} n
151
 * @param {number[]} i
152
 * @returns {number[]}
153
 * @private
154
 */
155
function rotr64 (n, i) {
156 12512
  if (i < 32) {
157 7344
    return [n[0] >>> i | n[1] << (32 - i), n[1] >>> i | n[0] << (32 - i)]
158
  }
159 5168
  return [
160
    n[1] >>> (i - 32) | n[0] << (32 - (i - 32)),
161
    n[0] >>> (i - 32) | n[1] << (32 - (i - 32))
162
  ]
163
}
164
/**
165
 * @param {number[]} a
166
 * @param {number[]} b
167
 * @returns {number[]}
168
 * @private
169
 */
170
function xor64 (a, b) {
171 13872
  return [(a[0] ^ b[0]), (a[1] ^ b[1])]
172
}
173
/**
174
 * @param {number[]} a
175
 * @param {number[]} b
176
 * @returns {number[]}
177
 * @private
178
 */
179
function and64 (a, b) {
180 6800
  return [(a[0] & b[0]), (a[1] & b[1])]
181
}
182
/**
183
 * @param {number[]} n
184
 * @returns {number[]}
185
 * @private
186
 */
187
function not64 (n) {
188 1360
  return [~n[0], ~n[1]]
189
}
190
/**
191
 * @param {number[]} a
192
 * @param {number[]} b
193
 * @returns {number[]}
194
 * @private
195
 */
196
function sum64 (a, b) {
197 12920
  const x = [0, 0, 0, 0]
198 12920
  x[3] = (a[1] & 0xffff) + (b[1] & 0xffff)
199 12920
  x[2] = (a[1] >>> 16) + (b[1] >>> 16) + (x[3] >>> 16)
200 12920
  x[1] = (a[0] & 0xffff) + (b[0] & 0xffff) + (x[2] >>> 16)
201 12920
  x[0] = (a[0] >>> 16) + (b[0] >>> 16) + (x[1] >>> 16)
202 12920
  return [((x[0] & 0xffff) << 16) + (x[1] & 0xffff), ((x[2] & 0xffff) << 16) + (x[3] & 0xffff)]
203
}
204
205 1
exports.sha512 = sha512
206
exports.sha512PreProcess = sha512PreProcess
207